home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 090 / byte0387.arc / DAWSON.ARC / SIMGEO.C < prev    next >
Encoding:
C/C++ Source or Header  |  1985-07-12  |  5.1 KB  |  153 lines

  1. /***********************************************\
  2. *                             *
  3. *   simgeo.c = Geometric Operations for SIMPP:  *
  4. *   Simple IMage Processing Package.            *
  5. *   Copyright (c) 1987, Benjamin M. Dawson      *
  6. *      Edit Version: 1.2 : Jan-30-87            *
  7. *                             *
  8. \***********************************************/
  9.  
  10. #include "simpp.h"
  11.  
  12. extern char *malloc();
  13.  
  14. /* rotate = Rotate clockwise by 90 degrees.  Limited to an area of MEMSIZE,
  15.  * and should be a square area.
  16.  */
  17. int rotate(x,y,dx,dy)
  18. register int x,y;    /* Start of area to rotate */
  19. int dx,dy;        /* Size of area to rotate */
  20. {
  21.     register int i;
  22.     unsigned long nl;
  23.     PIXEL *buf, *bp;
  24.  
  25. #ifdef CHECK
  26.     if (check_area(x,y,dx,dy,"<rotate>") == ERROR)
  27.         return(ERROR);
  28. #endif
  29.  
  30. /* Compute the number of bytes in the image area to be rotated */
  31.     nl = ((long)dx)*((long)dy)*((long)sizeof(PIXEL));
  32. #ifdef CHECK
  33.     if (nl > MEMSIZE) {
  34.         printf("<rotate> Area too large!\n");
  35.         return(ERROR);
  36.     }
  37.     if (dx != dy) {
  38.         printf("(rotate) Warning: area not square, may write\n");
  39.         printf("     outside of the image memory!\n");
  40.     }
  41. #endif
  42. /* Allocate a large buffer for storage */
  43.     buf = bp = (PIXEL *)malloc(((unsigned int)nl));
  44.  
  45. /* Read in image */
  46.     if (read_area(x,y,dx,dy,bp) == ERROR) {
  47.         printf("<rotate> Can't read area!\n");
  48.         return(ERROR);
  49.     }
  50.  
  51. /* Write it out the other way */
  52.     while (dy--) {
  53.         for (i = 0 ; i < dx ; i++) write_pixel(x,y+i,*bp++);
  54.         x++;
  55.     }
  56.  
  57.     free(buf);
  58.     return(OK);
  59. }
  60.  
  61. /* ================================================================ */
  62.  
  63. /* stretch = Enlarge image size by stretching the image by xs,ys.
  64.  * The image is stretched into the same area, starting from the
  65.  * upper,left corner.  Limited to a MEMSIZE area, and uses interpolation
  66.  * to smooth pixel values.
  67.  */
  68. stretch(x,y,dx,dy,xs,ys)
  69. int x,y;        /* Start of source AND destination */
  70. int dx,dy;        /* Size of Source AND destination */
  71. double xs,ys;        /* X,Y scale factors */
  72. {
  73.     register int i,j;
  74.     int ix,iy;
  75.     unsigned long nl;
  76.     PIXEL *buf, *bp, *p;
  77.     double A,B,C,D,xAB,xCD,xx,yy,V;
  78.  
  79. #ifdef CHECK
  80.     if (check_area(x,y,dx,dy,"<stretch>") == ERROR)
  81.         return(ERROR);
  82.  
  83. /* Must stretch -- shrinking will cause indexing problems */
  84.     if ((xs < 1.0) || (ys < 1.0)) {
  85.         printf("<stretch> Scale factors must be > 1.0!\n");
  86.         return(ERROR);
  87.     }
  88. #endif
  89.  
  90.     nl = ((long)dx)*((long)dy);
  91. #ifdef CHECK
  92.     if (nl > MEMSIZE) {
  93.         printf("<stretch> Area too large!\n");
  94.         return(ERROR);
  95.     }
  96. #endif
  97.  
  98.     buf = bp = (PIXEL *)malloc((unsigned int)nl*sizeof(PIXEL));
  99.     if (read_area(x,y,dx,dy,bp) == ERROR) return(ERROR);
  100.  
  101. /* Method:  We compute fractional addresses (xx,yy) that indicate where
  102.  * the source "pixel" would be.  Since this address, in general, will fall
  103.  * between pixels, we approximate the value by bi-linear interpolation.
  104.  * We round the fractional addresses down to integer values to get the
  105.  * address (ix,iy) of nearest real pixel to the top and left of the desired
  106.  * "interpolated pixel".  We then subtract this address from the interpolated
  107.  * pixel address to get the fraction of address between the four pixels
  108.  * surrounding the interpolated pixel (xx = xx - ix, yy = yy -iy).  The
  109.  * address of the nearest top, left pixel (called pixel A) is incremented
  110.  * to get pixel values for the four pixels surrounding the interpolated
  111.  * pixel.  Thus we have a 2 by 2 matrix of values:
  112.  *            A   B
  113.  *            C   D
  114.  * To get the interpolated value, we first compute the linear weighted
  115.  * value at distance xx between A and B and at xx between C and D.  These
  116.  * two values (yAB and yCD) are weighted by yy to get the interpolated
  117.  * value.
  118.  */
  119. /* Compute address of the "interpolated pixel" and the nearest real pixel */
  120.     for (i = 1 ; i < dy ; i++) {    /* Don't change first row */
  121.       yy = (double)(i-1)/ys;    /* Compute y address for source */
  122.       iy = (int)yy;            /* Round to integer */
  123.       yy = yy - (double)iy;        /* Leave only fraction of address */
  124.       bp = buf + iy*dx;        /* Compute pointer to nearest line */
  125.       for (j = 1 ; j < dx ; j++) {    /* Don't change first column */
  126.         xx = (double)(j-1)/xs;    /* Compute x address for source */
  127.         ix = (int)xx;        /* Rount to integer */
  128.         xx = xx - (double)ix;    /* Leave only fraction of address */
  129. /* Compute the value of the four nearest neighbor pixels */
  130.         p = bp + ix;        /* Pointer to top, left real pixel */
  131.         A = (double)(*p++);    /* Top, left real pixel */
  132.         B = (double)(*p);    /* Top, right real pixel */
  133.         D = (double)(*(p + dx));/* Bottom, right real pixel */
  134.         C = (double)(*(p + dx - 1));    /* Bottom, left real pixel */
  135. /* Compute the linear interpolated values (A to B and C to D) */
  136.         xAB = A + (B - A)*xx;    /* xx of the way between A and B */
  137.         xCD = C + (D - C)*xx;    /* xx of the way between C and D */
  138. /* Compute the (bi)linear interpolated value between xAB and xCD.  This is
  139.  * yy of the way between xAB and xCD.  Round the value by adding 0.5 */
  140.         V = xAB + ((xCD - xAB)*yy) + 0.5;
  141. /* Write out interpolated value */
  142.         write_pixel(x+j,y+i,(PIXEL)V);
  143.       }
  144.     }
  145.  
  146.     free(buf);
  147.     return(OK);
  148. }
  149.  
  150. /* ================ End of simgeo.c ================ */
  151.     
  152. /* <-- FILE BREAK --> */
  153.